﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;

using tactics.Abilities;

namespace tactics
{
    using Coord = Utility.Pair<int, int>;
    using HighlightMap = Dictionary<int, int>;

    struct SimpleCache
    {
        public int X { get; set; }
        public int Y { get; set; }
        public Unit LastUnit { get; set; }
        public Ability LastAbility { get; set; }

        public void Cache(Unit unit, Ability ability)
        {
            LastUnit = unit;
            LastAbility = ability;
            X = unit.X;
            Y = unit.Y;
        }

        public bool IsCached(Unit unit, Ability ability)
        {
            return (LastUnit == unit        &&
                    LastAbility == ability  &&
                    X == unit.X             &&
                    Y == unit.Y);
        }
    }

    class AbilityHighlighter
    {
        HighlightMap highlightMap;
        TerrainMap terrainMap;
        SimpleCache simpleCache;

        public AbilityHighlighter(TerrainMap terrainMapIn)
        {
            terrainMap = terrainMapIn;

            simpleCache = new SimpleCache();
            highlightMap = new HighlightMap();
        }

        public HighlightMap GenerateHighlight(Unit unit, Player player, Ability ability)
        {
            // very simple cache check -- hold onto last highlight map generated, return if same
            if (simpleCache.IsCached(unit, ability))
                return highlightMap;
            simpleCache.Cache(unit, ability);

            highlightMap = new HighlightMap();            
            Vector3 position = new Vector3(unit.X, terrainMap.GetHeight(unit.X, unit.Y), unit.Y);

            for (int y = unit.Y - ability.Range; y <= unit.Y + ability.Range; ++y)
            {
                for (int x = unit.X - ability.Range; x <= unit.X + ability.Range; ++x)
                {
                    if ((y >= 0 && y < terrainMap.Height - 1) &&
                        (x >= 0 && x < terrainMap.Width - 1))
                    {
                        int highlight = -1;
                        Coord coord = new Coord(x, y);

                        Vector3 direction = new Vector3(x, terrainMap.GetHeight(x, y), y) - position;

                        Ray ray = new Ray(position, direction);
                        var collision = Nuclex.Ray3HeightFieldCollider.findQuadContacts(ray.Position, ray.Direction, x, y, terrainMap.NuclexHeightField);

                        //TODO: fix line of sight check
                        //if (!collision.HasContact)
                        {
                            int playerId = terrainMap.GetPlayerAt(coord);

                            if (playerId != -1 && playerId != player.Number)
                                highlight = 1;
                            else if (playerId == player.Number)
                                highlight = 2;
                            else
                                highlight = 0;
                        }

                        highlightMap[terrainMap.AtCoord(x, y)] = highlight;
                    }
                }
            }

            return highlightMap;
        }
    }
}
